home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
tsr
/
xsnap.zip
/
XSNAP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-09
|
33KB
|
1,216 lines
/*
* xsnap -- take a snapshot of a portion of the screen.
*
* Copyright 1989 Clauss Strauch
* cbs@cad.cs.cmu.edu
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted.
* This software is provided "as is", without express or implied warranty.
*
* Modified by Bill Janssen janssen@parc.xerox.com
* add -xwd, -atk and -region options
* Modified by Arnaud Le Hors lehors@mirsa.inria.fr November 14 1990
* fix code about region option
* add -xpm option
*
*/
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xos.h>
#include <X11/Xutil.h>
#include <X11/cursorfo.h>
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/* Leave arguments as globals, since there are so many of them.
* They'll only be referenced in process_args and main.
*/
char *display_string = NULL; /* display we'll open */
int border_width = 2; /* border_width of the snapshot window */
int start_iconic = FALSE; /* start snap window in iconic state? */
char *color_name = NULL; /* user-supplied name of border color */
char *window_geom_string = NULL; /* geometry of snapshot window */
char *icon_geom_string = NULL; /* icon geometry */
char *region_geom_string = NULL; /* location of region to copy */
char *app_name = "xsnap"; /* name of application for window manager */
int xwd_output = FALSE; /* store in xwd format */
int atk_output = FALSE; /* store in ATK format */
int xpm_output = FALSE; /* store in XPM format */
char *output_file_name = NULL; /* file to store in */
int cut_buffer = FALSE; /* store in cutbuffer in ATK format? */
int grab_server = TRUE; /* grab the server? */
int display_in_window = TRUE; /* display in window after snap? */
/*
* create_event_window returns the ID of a InputOnly window that covers
* the given window.
*/
Window create_event_window(a_display,a_window, init_cursor)
Display *a_display;
Window a_window;
{
XSetWindowAttributes xswa;
unsigned long xswa_valuemask;
Window root_win;
Window event_window;
unsigned int win_width, win_height;
unsigned int win_border_width, win_depth;
int win_x, win_y;
/* get the geometry of the window */
XGetGeometry(a_display, a_window, &root_win, &win_x, &win_y,
&win_width, &win_height, &win_border_width, &win_depth);
/* make an input only window to get events from */
xswa.cursor = init_cursor;
xswa.override_redirect = True;
xswa.event_mask = ButtonPressMask | ButtonReleaseMask | Button1MotionMask;
xswa_valuemask = CWCursor | CWOverrideRedirect | CWEventMask;
event_window = XCreateWindow(a_display, a_window, win_x, win_y, win_width,
win_height, 0, 0, InputOnly, CopyFromParent,
xswa_valuemask, &xswa);
return(event_window);
}
/*
* draw box draws a box on the given window, with the given GC
*
*/
void draw_box(a_display, a_window, a_gc, x1, y1, x2, y2)
GC a_gc;
Window a_window;
Display *a_display;
int x1, y1, x2, y2;
{
XSegment segments[4];
segments[0].x1 = (short)x1;
segments[0].y1 = (short)y1;
segments[0].x2 = (short)x1;
segments[0].y2 = (short)y2;
segments[1].x1 = (short)x1;
segments[1].y1 = (short)y1;
segments[1].x2 = (short)x2;
segments[1].y2 = (short)y1;
segments[2].x1 = (short)x2;
segments[2].y1 = (short)y2;
segments[2].x2 = (short)x1;
segments[2].y2 = (short)y2;
segments[3].x1 = (short)x2;
segments[3].y1 = (short)y2;
segments[3].x2 = (short)x2;
segments[3].y2 = (short)y1;
XDrawSegments(a_display, a_window, a_gc, segments, 4);
}
/*
* get_region
* takes as input:
* display
* window to get region from
* pointers to x1, y1, width, height
*
* returns: the position and width and height of a
* user selected region via the given pointers.
*
*/
get_region(a_display, a_window, x, y, width, height)
Display *a_display;
Window a_window;
int *x, *y;
unsigned int *height, *width;
{
Window event_window;
Cursor up_right_curs, up_left_curs;
Cursor low_right_curs, low_left_curs;
Cursor current_cursor;
int done;
int init_x, init_y;
int last_x, last_y;
XEvent event;
GC xor_gc;
XGCValues xor_gc_values; /* for creating xor_gc */
unsigned long xor_gc_valuemask; /* valuemask for creating xor_gc */
/* make the GC and cursors we'll need */
up_right_curs = XCreateFontCursor(a_display, XC_ur_angle);
up_left_curs = XCreateFontCursor(a_display, XC_ul_angle);
low_right_curs = XCreateFontCursor(a_display, XC_lr_angle);
low_left_curs = XCreateFontCursor(a_display, XC_ll_angle);
xor_gc_valuemask = GCFunction | GCSubwindowMode | GCForeground;
xor_gc_values.function = GXxor;
xor_gc_values.foreground = 0xfd;
xor_gc_values.subwindow_mode = IncludeInferiors;
xor_gc = XCreateGC(a_display, a_window, xor_gc_valuemask, &xor_gc_values);
event_window = create_event_window(a_display, a_window,up_left_curs);
XMapRaised(a_display, event_window);
if (XGrabPointer(a_display, event_window, True,
ButtonPressMask,
GrabModeAsync, GrabModeAsync, None, up_left_curs,
CurrentTime) != 0)
{
fprintf(stderr, "Cannot grab pointer.");
exit(1);
}
/* get the initial button press */
done = FALSE;
while (! done)
{
XNextEvent(a_display, &event);
switch(event.type)
{
case MappingNotify:
XRefreshKeyboardMapping(&event);
break;
case ButtonPress:
if (event.xbutton.button == 1)
{
init_x = event.xbutton.x;
init_y = event.xbutton.y;
done = TRUE;
break;
}
}
}
/* now we have the location of one corner of the box. change the cursor,
* and have the user drag out the area.
*/
current_cursor = low_right_curs;
last_x = init_x;
last_y = init_y;
XChangeActivePointerGrab(a_display, ButtonReleaseMask | Button1MotionMask,
current_cursor, CurrentTime);
done = FALSE;
draw_box(a_display, a_window, xor_gc, init_x, init_y, last_x, last_y);
while (! done)
{
XNextEvent(a_display, &event);
switch(event.type)
{
case MappingNotify:
XRefreshKeyboardMapping(&event);
break;
case MotionNotify:
draw_box(a_display, a_window, xor_gc,
init_x, init_y, last_x, last_y); /* erase old */
last_x = event.xmotion.x;
last_y = event.xmotion.y;
draw_box(a_display, a_window, xor_gc,
init_x, init_y, last_x, last_y); /* draw new */
/* Change cursor to correspond to position of pointer */
if ((init_x < last_x) && (init_y < last_y)
&& (current_cursor != low_right_curs))
{
current_cursor = low_right_curs;
XChangeActivePointerGrab(a_display,
ButtonReleaseMask | Button1MotionMask,
low_right_curs, CurrentTime);
}
else if ((last_x < init_x) && (last_y < init_y)
&& (current_cursor != up_left_curs))
{
current_cursor = up_left_curs;
XChangeActivePointerGrab(a_display,
ButtonReleaseMask | Button1MotionMask,
up_left_curs, CurrentTime);
}
else if ((init_x < last_x) && (last_y < init_y)
&& (current_cursor != up_right_curs))
{
current_cursor = up_right_curs;
XChangeActivePointerGrab(a_display,
ButtonReleaseMask | Button1MotionMask,
up_right_curs, CurrentTime);
}
else if ((last_x < init_x) && (init_y < last_y)
&& (current_cursor != low_left_curs))
{
current_cursor = low_left_curs;
XChangeActivePointerGrab(a_display,
ButtonReleaseMask | Button1MotionMask,
low_left_curs, CurrentTime);
}
break;
case ButtonRelease:
if (event.xbutton.button == 1)
{
done = TRUE;
draw_box(a_display, a_window, xor_gc,
init_x, init_y, last_x, last_y); /* erase last box drawn */
}
break;
}
}
XFlush(a_display); /* gets rid of last box on screen */
if (init_x < last_x) *x = init_x;
else *x = last_x;
if (init_y < last_y) *y = init_y;
else *y = last_y;
*width = (unsigned int)abs(last_x - init_x);
*height = (unsigned int)abs(last_y - init_y);
/* clean up after ourself: */
XDestroyWindow(a_display, event_window);
XFreeGC(a_display, xor_gc);
/* we'll let the caller ungrab the pointer */
}
/*
* get_pixmap_region
*
* input :
* a display, a window, x, y, width, height, interactive.
* if interactive, the user is prompted for a region,
* other wise the given region is copied to a pixmap.
* returns : a pixmap containing a copy of a user-specified area
* of the given window;
*
*/
Pixmap get_pixmap_region(a_display, a_screen, a_window, a_gc, x, y,
width, height, depth, interactive)
Display *a_display;
GC a_gc;
int a_screen;
Window a_window;
int *x, *y;
unsigned int *width, *height, *depth;
int interactive;
{
int reg_x, reg_y;
unsigned int reg_width, reg_height;
Pixmap pixmap_returned;
int return_flag;
int junk_root, junk_left, junk_top, junk_width, junk_height, junk_border_width;
if (interactive){
get_region(a_display, a_window, ®_x, ®_y,
®_width, ®_height);
*x = reg_x;
*y = reg_y;
*width = reg_width;
*height = reg_height;
}
/* Use the depth of `a_window' for the depth of the pixmap */
XGetGeometry (a_display, a_window, &junk_root, &junk_left, &junk_top,
&junk_width, &junk_height, &junk_border_width, depth);
pixmap_returned = XCreatePixmap(a_display,
DefaultRootWindow(a_display),
*width, *height, *depth);
/* now copy the area we specified */
XCopyArea(a_display, a_window, pixmap_returned, a_gc, *x, *y,
*width, *height, 0, 0);
if (interactive) XUngrabPointer(a_display, CurrentTime);
return(pixmap_returned);
}
/*
* X error handler for, mainly for future use
*/
int my_X_error_handler(display, myerr)
Display *display;
XErrorEvent *myerr;
{
char msg[80];
/* if we get a BadAlloc error, it's probably 'cuz we couldn't allocate
* the pixmap. Tell the user this.
*/
fprintf(stderr,"xsnap:\n");
if ((myerr->error_code) == BadAlloc)
{
fprintf(stderr, "Insufficient resources for operation.\n");
fprintf(stderr, "Probably not enough memory to allocate pixmap.\n");
}
/* Now print out the error string that X generates */
XGetErrorText(display, myerr->error_code, msg,80);
fprintf(stderr, "Error code %s\n", msg);
/* no way to continue, so we'll just bag it */
exit(1);
}
/*
* print a usage message to the user
*/
usage()
{
printf("%s\n", "Usage: xsnap [-options...]");
printf("%s\n", "Where options are:");
printf("%s\n", "[-display host:display] Display to connect to.");
printf("%s\n", "[-bd borderwidth] Color of border");
printf("%s\n", "[-bw borderwidth] Width of border");
printf("%s\n", "[-geometry geom] Geometry of snapshot window");
printf("%s\n", "[-icongeometry geom] Location of icon.");
printf("%s\n", "[-region geom] Region of screen to be copied.");
printf("%s\n", "[-iconic] Start up in iconic state");
printf("%s\n", "[-name name] Passed to window manager for name of window.");
printf("%s\n", "[-nograb] Don't grab server during specification of region.");
printf("%s\n", "[-xwd] Write to output in `xwd' format.");
printf("%s\n", "[-atk] Write to output in `atk' format.");
printf("%s\n", "[-xpm] Write to output in `xpm' format.");
printf("%s\n", "[-file filename] Write output to file `filename'.");
printf("%s\n", "[-cutbuffer] Store in cutbuffer in Andrew raster format.");
printf("%s\n", "[-noshow] Don't display in window.");
exit(1);
}
/*
* get the arguments. arguments are matched to the first
* distinguishing substring.
*/
process_args(argc, argv)
int argc;
char **argv;
{
int i;
for (i = 1; i < argc; i++)
{
if (strncmp(argv[i], "-h", 2) == 0)
{
usage();
continue;
}
if (strncmp(argv[i], "-display", 2) == 0)
{
display_string = argv[++i];
continue;
}
if (strncmp(argv[i], "-bw", 3) == 0)
{
border_width = atoi(argv[++i]);
continue;
}
if (strncmp(argv[i], "-bd", 3) == 0)
{
color_name = argv[++i];
continue;
}
if (strncmp(argv[i], "-ge", 3) == 0)
{
window_geom_string = argv[++i];
continue;
}
if (strncmp(argv[i], "-icong", 6) == 0)
{
icon_geom_string = argv[++i];
continue;
}
if (strncmp(argv[i], "-r", 2) == 0)
{
region_geom_string = argv[++i];
continue;
}
if (strncmp(argv[i], "-iconi", 6) == 0)
{
start_iconic = TRUE;
continue;
}
if (strncmp(argv[i], "-na", 3) == 0)
{
app_name = argv[++i];
continue;
}
if (strncmp(argv[i], "-nog", 4) == 0)
{
grab_server = FALSE;
continue;
}
if (strncmp(argv[i], "-nos", 4) == 0)
{
display_in_window = FALSE;
continue;
}
if (strncmp(argv[i], "-xwd", 4) == 0)
{
xwd_output = TRUE;
continue;
}
if (strncmp(argv[i], "-atk", 4) == 0)
{
atk_output = TRUE;
continue;
}
if (strncmp(argv[i], "-xpm", 4) == 0)
{
xpm_output = TRUE;
continue;
}
if (strncmp(argv[i], "-file", 5) == 0)
{
output_file_name = argv[++i];
continue;
}
if (strncmp(argv[i], "-cutb", 5) == 0)
{
cut_buffer = TRUE;
continue;
}
usage();
}
}
/*
* Get the XColors of all pixels in image - returns # of colors
*/
int Get_XColors(dpy, win_info, colors)
Display *dpy;
XWindowAttributes *win_info;
XColor **colors;
{
int i, ncolors;
if (!win_info->colormap)
return(0);
if (win_info->visual->class == TrueColor ||
win_info->visual->class == DirectColor)
return(0); /* XXX punt for now */
ncolors = win_info->visual->map_entries;
if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors)))
fprintf (stderr, "xsnap: out of memory attempting to allocate colors\n");
for (i=0; i<ncolors; i++)
(*colors)[i].pixel = i;
XQueryColors(dpy, win_info->colormap, *colors, ncolors);
return(ncolors);
}
/*
* Determine the pixmap size.
*/
int Image_Size(image, format)
XImage *image;
int format;
{
if (format != ZPixmap)
return(image->bytes_per_line * image->height * image->depth);
return(image->bytes_per_line * image->height);
}
_swapshort (bp, n)
register char *bp;
register unsigned n;
{
register char c;
register char *ep = bp + n;
while (bp < ep) {
c = *bp;
*bp = *(bp + 1);
bp++;
*bp++ = c;
}
}
_swaplong (bp, n)
register char *bp;
register unsigned n;
{
register char c;
register char *ep = bp + n;
register char *sp;
while (bp < ep) {
sp = bp + 3;
c = *sp;
*sp = *bp;
*bp++ = c;
sp = bp + 1;
c = *sp;
*sp = *bp;
*bp++ = c;
bp += 2;
}
}
#ifdef ATK
write_atk_bytes (file, curbyte, curcount)
FILE *file;
unsigned char curbyte;
unsigned int curcount;
{
/* codes for data stream */
#define WHITEZERO 'f'
#define WHITETWENTY 'z'
#define BLACKZERO 'F'
#define BLACKTWENTY 'Z'
#define OTHERZERO 0x1F
#define WHITEBYTE 0x00
#define BLACKBYTE 0xFF
/* WriteRow table for conversion of a byte value to two character hex representation */
static unsigned char hex[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
switch (curbyte)
{
case WHITEBYTE:
while (curcount > 20)
fputc(WHITETWENTY, file),
curcount -= 20;
fputc(WHITEZERO + curcount, file);
break;
case BLACKBYTE:
while (curcount > 20)
fputc(BLACKTWENTY, file),
curcount -= 20;
fputc(BLACKZERO + curcount, file);
break;
default:
while (curcount > 16)
fputc(OTHERZERO+16, file),
fputc(hex[curbyte / 16], file),
fputc(hex[curbyte & 15], file),
curcount -= 16;
if (curcount > 1)
fputc(OTHERZERO+curcount, file);
else ; /* the byte written will represent a single instance */
fputc(hex[curbyte / 16], file);
fputc(hex[curbyte & 15], file);
}
}
process_atk_byte (pcurcount, pcurbyte, file, newbyte, eolflag)
int *pcurcount;
unsigned char *pcurbyte;
FILE *file;
unsigned char newbyte;
int eolflag;
{
int curcount = *pcurcount;
unsigned char curbyte = *pcurbyte;
if (*pcurcount < 1)
{
*pcurbyte = newbyte;
*pcurcount = 1;
}
else if (newbyte == *pcurbyte)
{
*pcurcount = *pcurcount + 1;
}
else
{
write_atk_bytes (file, *pcurbyte, *pcurcount);
*pcurcount = 1;
*pcurbyte = newbyte;
}
if (eolflag)
{
write_atk_bytes (file, *pcurbyte, *pcurcount);
fprintf (file, " |\n");
*pcurcount = 0;
*pcurbyte = 0;
}
}
save_as_atk_file (display, screen, win_info, pixmap, width, height, depth)
Display *display;
int screen;
XWindowAttributes *win_info;
Pixmap pixmap;
unsigned int width, height, depth;
{
XColor *colors;
int ncolors, i, *color_translate, crunch_to_bw;
XImage *image;
FILE *output;
unsigned char curbyte, newbyte;
int curcount, gather, line, col;
image = XGetImage (display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
if (!image) {
fprintf (stderr, "xsnap: unable to get image at %dx%d+%d+%d\n",
width, height, 0, 0);
exit (1);
}
/*
* Find the output file
*/
if (output_file_name != NULL)
output = fopen (output_file_name, "w+");
if (output_file_name == NULL || output == NULL)
output = (stdout);
/*
* Set crunch-to-black-and-white flag
*/
if (crunch_to_bw = (image->depth > 1))
{
ncolors = Get_XColors(display, win_info, &colors);
color_translate = (int *) malloc (sizeof(int) * ncolors);
for (i = 0; i < ncolors; i += 1)
color_translate[colors[i].pixel] = ((.30 * colors[i].red + .59 * colors[i].green + .11 * colors[i].blue) > 0x8000) ? 0 : 1;
}
#define CRUNCHPIXEL(pix) ((crunch_to_bw)?(color_translate[(pix)]):(pix))
#define DEFAULTSCALE (1<<16)
#define RASTERVERSION 2
fprintf(output, "\\begindata{raster,%d}\n", 1);
fprintf(output, "%ld %ld %ld %ld ", RASTERVERSION,
0, DEFAULTSCALE, DEFAULTSCALE);
fprintf(output, "%ld %ld %ld %ld\n",
0, 0, width, height); /* subraster */
fprintf(output, "bits %ld %ld %ld\n", 1, width, height);
for (line = 0; line < height; line += 1)
{
gather = 0;
newbyte = 0;
curbyte = 0;
curcount = 0;
col = 0;
while (col < width)
{
if (gather > 7)
{
process_atk_byte (&curcount, &curbyte, output, newbyte, FALSE);
gather = 0;
newbyte = 0;
}
newbyte = (newbyte << 1) | CRUNCHPIXEL(XGetPixel(image, col, line));
gather += 1;
col += 1;
}
if (gather > 0)
{
newbyte = (newbyte << (8 - gather));
process_atk_byte (&curcount, &curbyte, output, newbyte, TRUE);
}
}
fprintf(output, "\\enddata{raster, %d}\n", 1);
if (output != stdout)
fclose (output);
}
#endif
#include "X11/XWDFile.h"
save_as_xwd_file (display, screen, win_info, pixmap, width, height, depth)
Display *display;
int screen;
XWindowAttributes *win_info;
Pixmap pixmap;
unsigned int width, height, depth;
{
unsigned long swaptest = 1;
XColor *colors;
unsigned buffer_size;
int win_name_size;
int header_size;
int ncolors, i;
char *win_name;
XImage *image;
int absx, absy, x, y;
int dwidth, dheight;
int bw;
XWDFileHeader header;
FILE *output;
image = XGetImage (display, pixmap, 0, 0, width, height, AllPlanes, ZPixmap);
if (!image) {
fprintf (stderr, "xsnap: unable to get image at %dx%d+%d+%d\n",
width, height, 0, 0);
exit (1);
}
/*
* Find the output file
*/
if (output_file_name != NULL)
output = fopen (output_file_name, "w+");
if (output_file_name == NULL || output == NULL)
output = (stdout);
/*
* Determine the pixmap size.
*/
buffer_size = Image_Size(image, ZPixmap);
ncolors = Get_XColors(display, win_info, &colors);
/*
* Calculate header size.
*/
header_size = sizeof(header);
/*
* Write out header information.
*/
header.header_size = (xwdval) header_size;
header.file_version = (xwdval) XWD_FILE_VERSION;
header.pixmap_format = (xwdval) ZPixmap;
header.pixmap_depth = (xwdval) image->depth;
header.pixmap_width = (xwdval) image->width;
header.pixmap_height = (xwdval) image->height;
header.xoffset = (xwdval) image->xoffset;
header.byte_order = (xwdval) image->byte_order;
header.bitmap_unit = (xwdval) image->bitmap_unit;
header.bitmap_bit_order = (xwdval) image->bitmap_bit_order;
header.bitmap_pad = (xwdval) image->bitmap_pad;
header.bits_per_pixel = (xwdval) image->bits_per_pixel;
header.bytes_per_line = (xwdval) image->bytes_per_line;
header.visual_class = (xwdval) win_info->visual->class;
header.red_mask = (xwdval) win_info->visual->red_mask;
header.green_mask = (xwdval) win_info->visual->green_mask;
header.blue_mask = (xwdval) win_info->visual->blue_mask;
header.bits_per_rgb = (xwdval) win_info->visual->bits_per_rgb;
header.colormap_entries = (xwdval) win_info->visual->map_entries;
header.ncolors = ncolors;
header.window_width = (xwdval) win_info->width;
header.window_height = (xwdval) win_info->height;
header.window_x = 0;
header.window_y = 0;
header.window_bdrwidth = (xwdval) win_info->border_width;
if (*(char *) &swaptest) {
_swaplong((char *) &header, sizeof(header));
for (i = 0; i < ncolors; i++) {
_swaplong((char *) &colors[i].pixel, sizeof(long));
_swapshort((char *) &colors[i].red, 3 * sizeof(short));
}
}
(void) fwrite((char *)&header, sizeof(header), 1, output);
/*
* Write out the color maps, if any
*/
(void) fwrite((char *) colors, sizeof(XColor), ncolors, output);
/*
* This copying of the bit stream (data) to a file is to be replaced
* by an Xlib call which hasn't been written yet. It is not clear
* what other functions of xwd will be taken over by this (as yet)
* non-existant X function.
*/
(void) fwrite(image->data, (int) buffer_size, 1, output);
/*
* close the file
*/
if (output != (stdout))
fclose (output);
/*
* free the color buffer.
*/
if(ncolors > 0) free(colors);
/*
* Free image
*/
XDestroyImage(image);
}
#ifdef XPM
#include "xpm.h"
save_as_xpm_file (display, screen, win_info, pixmap, width, height, depth)
Display *display;
int screen;
XWindowAttributes *win_info;
Pixmap pixmap;
unsigned int width, height, depth;
{
XWritePixmapFile(display, win_info->colormap, output_file_name,
pixmap, width, height, NULL, 1, NULL);
}
#endif
save_in_cut_buffer (display, screen, pixmap, width, height, depth)
Display *display;
int screen;
Pixmap pixmap;
unsigned int width, height, depth;
{
}
exitXsnap(the_display, snapshot, snap_pixmap, copy_gc)
Display *the_display;
Window snapshot;
Pixmap snap_pixmap;
GC copy_gc;
{
if (snapshot != 0)
XDestroyWindow(the_display, snapshot);
XFreePixmap(the_display, snap_pixmap);
XFreeGC(the_display, copy_gc);
XCloseDisplay(the_display);
exit(0);
}
main(argc, argv)
int argc;
char **argv;
{
Display *the_display;
int the_screen;
XWMHints wmhints;
XEvent an_event;
GC copy_gc;
unsigned long copy_gc_valuemask;
XGCValues copy_gc_values;
long wmhints_mask;
XSizeHints wm_size_hints;
int x_return, y_return; /* for XParseGeometry */
int width_return, height_return; /* ditto */
int geom_mask; /* bitmask for XParseGeometry fields */
unsigned long border_color_pixel; /* pixel for border color */
XColor color;
Colormap cmap;
Window window_to_snap; /* always root window, now */
Window snapshot;
Cursor snap_cursor;
Pixmap snap_pixmap;
int reg_x, reg_y;
int icon_x, icon_y;
int snap_x, snap_y;
unsigned int snap_width, snap_height;
unsigned int reg_width, reg_height, reg_depth;
int done;
char buffer [4]; /* key press buffer for XLookupString */
int string_length; /* length of returned string */
XWindowAttributes window_attributes;
process_args(argc, argv);
XSetErrorHandler(my_X_error_handler);
if ((the_display = XOpenDisplay(display_string)) == NULL)
{
fprintf(stderr, "Cannot open display: %s\n",
XDisplayName(display_string));
exit(1);
}
XSetErrorHandler(my_X_error_handler);
the_screen = DefaultScreen(the_display);
window_to_snap = XRootWindow(the_display, the_screen);
/* make copy GC */
copy_gc_valuemask = GCSubwindowMode;
copy_gc_values.subwindow_mode = IncludeInferiors;
copy_gc = XCreateGC(the_display, window_to_snap, copy_gc_valuemask, ©_gc_values);
if (grab_server)
{
XGrabServer(the_display);
XSync(the_display, 0);
}
if (region_geom_string)
{
geom_mask = XParseGeometry(region_geom_string, ®_x, ®_y,
®_width, ®_height);
if ((geom_mask & XValue) && (geom_mask & YValue) &&
(geom_mask & WidthValue) && (geom_mask & HeightValue))
/* must specify complete geometry for region */
{
if (geom_mask & XNegative)
reg_x += DisplayWidth(the_display, the_screen) - reg_width;
if (geom_mask & YNegative)
reg_y += DisplayHeight(the_display, the_screen) - reg_height;
snap_pixmap = get_pixmap_region(the_display, the_screen,
window_to_snap, copy_gc,
®_x, ®_y, ®_width,
®_height, ®_depth, FALSE);
}
else {
if (grab_server) {
XUngrabServer(the_display);
XSync(the_display, 0);
}
usage();
}
}
else
snap_pixmap = get_pixmap_region(the_display, the_screen,
window_to_snap, copy_gc,
®_x, ®_y,
®_width, ®_height,
®_depth, TRUE);
/* ungrab the server */
if (grab_server) XUngrabServer(the_display);
if (display_in_window)
{
/* process border color */
cmap = DefaultColormap(the_display, the_screen);
if ((color_name) && (XParseColor(the_display, cmap, color_name, &color)) &&
(XAllocColor(the_display, cmap, &color)))
border_color_pixel = color.pixel;
else
border_color_pixel = WhitePixel(the_display, the_screen);
/*
* get location of our window(from the window_geom_string),
* and set up the size hints structure.
*/
wm_size_hints.flags = 0;
width_return = reg_width;
height_return = reg_height;
wm_size_hints.x = 0;
wm_size_hints.y = 0;
wm_size_hints.width = reg_width;
wm_size_hints.height = reg_height;
if (window_geom_string)
{
geom_mask = XParseGeometry(window_geom_string, &x_return,
&y_return, &width_return,
&height_return);
if (geom_mask & XValue)
{
if (geom_mask & XNegative)
wm_size_hints.x = DisplayWidth(the_display,
the_screen)
- width_return + x_return -
(border_width * 2);
else
wm_size_hints.x = x_return;
}
if (geom_mask & YValue)
{
if (geom_mask & YNegative)
wm_size_hints.y =
DisplayHeight(the_display, the_screen)
- height_return + y_return -
(border_width * 2);
else
wm_size_hints.y = y_return;
}
}
if ((geom_mask & XValue) || (geom_mask & YValue))
wm_size_hints.flags |= USPosition;
if ((geom_mask & WidthValue) || (geom_mask & HeightValue))
wm_size_hints.flags |= USSize;
wm_size_hints.width = width_return;
wm_size_hints.height = height_return;
snapshot = XCreateSimpleWindow(the_display,
XRootWindow(the_display, the_screen),
wm_size_hints.x, wm_size_hints.y,
wm_size_hints.width,
wm_size_hints.height, border_width,
border_color_pixel,
BlackPixel(the_display, the_screen));
if (window_geom_string)
XSetNormalHints(the_display, snapshot, &wm_size_hints);
XStoreName(the_display, snapshot, app_name);
wmhints_mask = 0;
if (start_iconic)
{
wmhints_mask |= StateHint;
wmhints.initial_state = IconicState;
}
x_return = y_return = 0;
/* Icon geometry is sorta broken, since we don't supply an icon, and
* there isn't any way I know of to get the geometry of the icon that
* the window manager will provide. So, we'll pretend that our icon
* is 32x32 (ugh).
*/
if (icon_geom_string)
{
geom_mask = XParseGeometry(icon_geom_string, &x_return,
&y_return, &width_return,
&height_return);
if (geom_mask & XValue)
{
if (geom_mask & XNegative)
wmhints.icon_x = DisplayWidth(the_display,
the_screen)
- 32 + x_return - (border_width * 2);
else
wmhints.icon_x = x_return;
}
if (geom_mask & YValue)
{
if (geom_mask & YNegative)
wmhints.icon_y = DisplayHeight(the_display,
the_screen)
- 32 + y_return - (border_width * 2);
else
wmhints.icon_y = y_return;
}
wmhints_mask |= IconPositionHint;
}
if (wmhints_mask)
{
wmhints.flags = wmhints_mask;
XSetWMHints(the_display, snapshot, &wmhints);
}
/* solicit expose events */
XSelectInput(the_display, snapshot, ExposureMask | KeyPressMask);
/* give it a different cursor */
snap_cursor = XCreateFontCursor(the_display, XC_gumby);
XDefineCursor(the_display, snapshot, snap_cursor);
/* set the background of the window to be the pixmap */
XSetWindowBackgroundPixmap (the_display, snapshot, snap_pixmap);
/* map it */
XMapRaised(the_display, snapshot);
XFlush (the_display);
}
if (xwd_output)
{
XGetWindowAttributes (the_display, window_to_snap,
&window_attributes);
save_as_xwd_file (the_display, the_screen, &window_attributes, snap_pixmap, reg_width, reg_height, reg_depth);
}
if (atk_output)
{
#ifdef ATK
XGetWindowAttributes (the_display, window_to_snap,
&window_attributes);
save_as_atk_file (the_display, the_screen, &window_attributes, snap_pixmap, reg_width, reg_height, reg_depth);
#else
printf("This version of xsnap has not be compiled with the atk feature,\n");
printf("recompile with ATK defined.\n");
#endif
}
if (xpm_output)
{
#ifdef XPM
XGetWindowAttributes (the_display, window_to_snap,
&window_attributes);
save_as_xpm_file (the_display, the_screen, &window_attributes, snap_pixmap, reg_width, reg_height, reg_depth);
#else
printf("This version of xsnap has not be compiled with the xpm feature,\n");
printf("recompile with XPM defined.\n");
#endif
}
if (cut_buffer)
save_in_cut_buffer (the_display, the_screen, snap_pixmap, reg_width, reg_height, reg_depth);
if (!display_in_window)
exitXsnap (the_display, NULL, snap_pixmap, copy_gc);
/* process events */
done = FALSE;
while (! done)
{
XNextEvent(the_display, &an_event);
switch (an_event.type)
{
case MappingNotify:
XRefreshKeyboardMapping(&an_event);
break;
case KeyPress:
string_length = XLookupString(&an_event, buffer,
sizeof(buffer),
NULL, NULL);
if ((string_length == 1) && ((buffer[0] == 'q') ||
(buffer[0] == 'Q') ||
(buffer[0] == '\003')))
{
/* clean up */
exitXsnap(the_display, snapshot, snap_pixmap, copy_gc);
done = TRUE;
}
break;
}
}
}